Spring Boot的validation套件提供豐富的資料檢核annotation,包括@Pattern
支援Regex,不過秉持少引用一個套件就少一份處理弱掃的風險,加上有的檢核還真的是複雜,所以不引用validation自己手工做一個。
因此,一開始我就弱化了Controller角色,所有method都將@RequestBody當作字串處理,回應一律用Object,方便Value Object轉成JSON。
@RestController
@Slf4j
@RequiredArgsConstructor
public class CRMController {
@Autowired
private CRMService crmService;
@PostMapping(value = "/getOldCust_Period", consumes = MediaType.APPLICATION_JSON_VALUE, produces = "application/json;charset=UTF-8")
public ResponseEntity<Object> getOldCust_Period(@RequestBody String inputVO) {
Object outputVO = this.crmService.getOldCust_Period(inputVO);
return ResponseEntity.ok(outputVO);
}
}
在客戶的弱掃軟體是Micro Focus,測試案例如下,會要求不得回覆HTTP Status 500。另一款弱掃軟體AppScan遇到以下測試個案例,會要求一律回HTTP Status 500
{"is_admin": true}
第一個validateJSON的檢核就包括了長度、JSON格式、JSON Key是否合法
private List<String> AFields = Arrays.asList(new String[]{"CUST_ID", "PROD_TYPE", "SEQ", "AMT"});
/**
* 檢核A電文JSON字串有無失當
* @param jsonStr
* @return 回null表示正常
*/
private ESBErrorVO validateJSON(String jsonStr) {
if (jsonStr != null && jsonStr.length() >= 2048) {
ESBErrorVO errorVO = new ESBErrorVO();
errorVO.setEMSGID("E005");
errorVO.setEMSGTXT(DenominatorService.EMSGTXT + ", 長度太長");
return errorVO;
}
ObjectMapper mapper = new ObjectMapper();
boolean valid = true;
try {
JsonNode rootNode = mapper.readTree(jsonStr);
Iterator<String> fieldNames = rootNode.fieldNames();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
if (!AFields.contains(fieldName)) {
valid = false;
}
}
} catch (Exception errJson) {
ESBErrorVO errorVO = new ESBErrorVO();
errorVO.setEMSGID("E005");
errorVO.setEMSGTXT("非JSON格式");
return errorVO;
}
if (!valid) {
ESBErrorVO errorVO = new ESBErrorVO();
errorVO.setEMSGID("E005");
errorVO.setEMSGTXT("帶不合法欄位");
return errorVO;
}
return null;
}
第二個檢核就針對每個欄位的value進行檢核,這時的ESBInputVO是透過Spring Boot的Jackson套件轉換,這原本是可以在Controller就可以透過@RequestBody ESBInputVO inputVO
做掉:
ObjectMapper mapper = new ObjectMapper();
ESBInputVO inputVO = mapper.readValue(jsonStr, ESBInputVO.class);
validateInputVO的內容,其中checkIDType這個method是Day 1的內容,檢核客戶ID是哪一種類型,這需求就無法使用validation套件的@Pattern
/**
* 檢核A上行電文欄位有無不當
* @param inputVO
* @return null表示沒錯誤
*/
private ESBErrorVO validateInputVO(ESBInputVO inputVO) {
ESBErrorVO errorVO = new ESBErrorVO();
StringBuffer sbErr = new StringBuffer();
if (inputVO == null) {
errorVO.setEMSGID("E005");
errorVO.setEMSGTXT("上行電文為空");
return errorVO;
}
String custId = inputVO.getCUST_ID();
if (this.checkIDType(custId) == null) {
sbErr.append("CUST_ID[").append(custId).append("]");
}
String prodType = inputVO.getPROD_TYPE();
if (prodType == null || !prodType.matches("[1-6]")) {
sbErr.append("PROD_TYPE[").append(prodType).append("]");
}
String amt = inputVO.getAMT();
if (amt == null || !amt.matches("[0-9]{1,16}")) {
sbErr.append("AMT[").append(amt).append("]");
}
String seq = inputVO.getSEQ();
if (seq == null || !seq.matches("([0-9A-Za-z]){7,20}")) {
sbErr.append("SEQ[").append(seq).append("]");
}
if (sbErr.length() > 0) {
errorVO.setEMSGID("E005");
errorVO.setEMSGTXT("上行電文欄位有誤:" + sbErr.toString());
return errorVO;
}
return null;
}